package com.kmxd.ams.app.event.efile.command;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.common.collect.Lists;
import com.kmxd.ams.client.archive.IArchiveFieldSvc;
import com.kmxd.ams.client.archive.IArchiveOssSettingSvc;
import com.kmxd.ams.client.archive.IArchiveTypeSvc;
import com.kmxd.ams.client.archive.dto.ArchiveOssSettingQueryDTO;
import com.kmxd.ams.client.archive.vo.ArchiveFieldListVO;
import com.kmxd.ams.client.archive.vo.ArchiveTypeVO;
import com.kmxd.ams.client.arrange.IBoxSvc;
import com.kmxd.ams.client.arrange.IDocumentSvc;
import com.kmxd.ams.client.arrange.IVolumeSvc;
import com.kmxd.ams.client.arrange.dto.DocumentDayQueryDTO;
import com.kmxd.ams.client.oss.IEfileRecordSvc;
import com.kmxd.ams.client.oss.vo.EfileRecordListVO;
import com.kmxd.ams.client.system.ISysConfigSvc;
import com.kmxd.ams.client.system.ISysFondsSvc;
import com.kmxd.ams.client.system.vo.SysFondsVO;
import com.kmxd.ams.core.common.constant.ArchConst;
import com.kmxd.ams.core.common.constant.ConfigConst;
import com.kmxd.ams.core.common.constant.Constants;
import com.kmxd.ams.core.common.enums.ArchStatusEnum;
import com.kmxd.ams.core.oss.template.OssTemplate;
import com.kmxd.ams.core.util.ConfigUtil;
import com.kmxd.ams.core.util.DynamicTableNameUtil;
import com.kmxd.ams.core.util.IdUtil;
import com.kmxd.ams.infra.arrange.base.BaseBO;
import com.kmxd.ams.infra.arrange.entity.Document;
import com.kmxd.ams.infra.oss.entity.EfileRecord;
import java.io.File;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 电子文件路径整理
 *
 * @author ZuoLG
 */
@Slf4j
@Component
@AllArgsConstructor
public class EfilePathArrangeCmd {
  private IArchiveOssSettingSvc archiveOssSettingSvc;
  private IArchiveFieldSvc fieldSvc;
  private IEfileRecordSvc efileSvc;
  private IDocumentSvc documentSvc;
  private ISysConfigSvc sysConfigSvc;
  private IBoxSvc boxSvc;
  private IVolumeSvc volumeSvc;
  private OssTemplate ossTemplate;
  private ISysFondsSvc sysFondsSvc;
  private IArchiveTypeSvc archiveTypeSvc;
  /** 归档 */
  @Transactional(rollbackFor = Exception.class)
  public void archivingEfile(BaseBO req) throws Exception {
    log.debug("docIds: {} ", req.toString());
    // 获取转换方式
    String transferConf = sysConfigSvc.getConfigContentByKey(ConfigConst.OSS_TRANSFER);
    // 转换后缀
    String transferExt = ConfigUtil.getVal(transferConf, ConfigConst.TRANSFER_EXT);
    // 1、获取分组规则
    ArchiveOssSettingQueryDTO ossQueryDTO =
        BeanUtil.copyProperties(req, ArchiveOssSettingQueryDTO.class);
    List<ArchiveFieldListVO> paths = archiveOssSettingSvc.getPath(ossQueryDTO);
    List<ArchiveFieldListVO> names = archiveOssSettingSvc.getName(ossQueryDTO);
    // 2、根据分组获取路径，更改路径及状态
    List<Document> listDocs = Lists.newArrayList();
    if (StrUtil.isNotBlank(req.getDocIds())) {
      BaseBO baseBO = BeanUtil.copyProperties(req, BaseBO.class);
      baseBO.setDocIds(req.getDocIds());
      DynamicTableNameUtil.setTableName(req.getTableId());
      listDocs = documentSvc.selectListByIds(baseBO);
    } else {
      // 查询档案库需要处理的数据-只查询当天
      DocumentDayQueryDTO documentReq = new DocumentDayQueryDTO();
      documentReq.setArchTypeId(req.getArchTypeId());
      documentReq.setTableId(req.getTableId());
      String startTime = DateUtil.format(DateUtil.date(), "yyyy-MM-dd 00:00:00");
      String endTime = DateUtil.format(DateUtil.date(), "yyyy-MM-dd 23:59:59");
      documentReq.setStartDate(startTime);
      documentReq.setEndDate(endTime);
      listDocs = documentSvc.selectListByDay(documentReq);
    }
    // 定时整理不存在盒、案卷的情况
    List<EfileRecord> efileUpdate = Lists.newArrayList();
    listDocs.forEach(
        item -> {
          item.setArchTypeId(req.getArchTypeId());
          item.setTableId(req.getTableId());
          SysFondsVO fonds = sysFondsSvc.view(item.getFondsId());
          ArchiveTypeVO archiveType = archiveTypeSvc.view(item.getArchTypeId());

          // 获取路径
          String path = getValue(item, paths, fonds, archiveType, true);
          String name = getValue(item, names, fonds, archiveType, false);
          if (StrUtil.isBlank(path) || StrUtil.isBlank(name)) {
            return;
          }
          String tableName = Constants.TABLE_NAME_EFILE + "_" + fonds.getAutoIndex();
          DynamicTableNameUtil.setTableName(tableName);
          List<EfileRecordListVO> efiles =
              efileSvc.selectListByDocIds(
                  req.getArchTypeId(), IdUtil.split(String.valueOf(item.getId())));
          // 增加序号
          AtomicReference<Integer> index = new AtomicReference<>(efiles.size() == 0 ? 0 : 1);
          efiles.forEach(
              efile -> {
                // 只有未移交整理过的文件才重新路径整理
                if (ObjectUtil.notEqual(efile.getMoveStatus(), 1L)) {
                  EfileRecord record = BeanUtil.copyProperties(efile, EfileRecord.class);
                  String newPath =
                      ossTemplate.separator()
                          + ossTemplate.getDefPath()
                          + path
                          + ossTemplate.separator();
                  String newName =
                      name + (index.get() == 0 ? "" : "-" + index.get()) + "." + efile.getExt();
                  String newPdfName =
                      name + (index.get() == 0 ? "" : "-" + index.get()) + "." + transferExt;
                  String rootPath =
                      NumberUtil.equals(efile.getArrangeStatus(), ArchStatusEnum.S1.getCode())
                          ? ossTemplate.getManagePath(efile.getDefPath())
                          : ossTemplate.getCollectPath(efile.getDefPath());
                  // 移动普通文件
                  ossTemplate.rename(
                      rootPath + efile.getPath(),
                      ossTemplate.getManagePath(efile.getDefPath()) + newPath + newName);
                  // 如果有转换后的文件，移动转换后的文件
                  if (StrUtil.isNotBlank(efile.getShowFilePath())) {
                    if (StrUtil.equals(transferExt, efile.getExt())) {
                      record.setShowFilePath(newPath + newName);
                    } else {
                      File pdfFile = FileUtil.file(rootPath + efile.getShowFilePath());
                      if (pdfFile.exists()) {
                        ossTemplate.rename(
                            rootPath + efile.getShowFilePath(),
                            ossTemplate.getManagePath(efile.getDefPath()) + newPath + newPdfName);
                        record.setShowFilePath(newPath + newPdfName);
                      }
                    }
                  }
                  record.setSaveFileName(newName);
                  record.setPath(newPath + newName);
                  record.setArrangeStatus(ArchStatusEnum.S1.getCode());
                  record.setMoveStatus(1L);
                  efileUpdate.add(record);
                  index.set(index.get() + 1);
                }
              });
        });
    efileSvc.updateBatchById(efileUpdate);
    DynamicTableNameUtil.setTableName(req.getTableId());
    documentSvc.updateBatchById(listDocs);
  }

  /**
   * 动态获取分组内容
   *
   * @param document
   * @param keys
   * @param path
   * @return
   */
  private String getValue(
      Document document,
      List<ArchiveFieldListVO> keys,
      SysFondsVO fonds,
      ArchiveTypeVO archiveType,
      boolean path) {
    JSONObject jsonObject = JSONUtil.parseObj(document);
    StringBuffer stringBuffer = new StringBuffer();
    keys.forEach(
        item -> {
          if (path) {
            stringBuffer.append("/");
          }
          if (ObjectUtil.equals(item.getDbFieldKey(), ArchConst.OSS_SETTING_ARCH_TYPE_KEY)) {
            stringBuffer.append(archiveType.getName());
          } else if (ObjectUtil.equals(item.getDbFieldKey(), ArchConst.OSS_SETTING_FONDS_KEY)) {
            stringBuffer.append(fonds.getName());
          } else {
            stringBuffer.append(
                jsonObject.getStr(
                    !StringUtils.isCamel(item.getDbFieldKey())
                        ? StringUtils.underlineToCamel(item.getDbFieldKey())
                        : item.getDbFieldKey()));
          }
        });
    return stringBuffer.toString();
  }
}
